package MyList;

import MyList.IList;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA
 * Description:  MyArrayList的实现
 * User: SEKI TOMOKI
 * Date: 2024-06-30
 * Time: 14:49
 */
public class MyArrayList implements IList {
    public int[] elements;
    public int usedSize;
    public static final int DEFAULT_SIZE = 10;

    public MyArrayList() {
        this.elements = new int[DEFAULT_SIZE];
    }
    public MyArrayList(int size) {
        this.elements = new int[size];
    }



    @Override
    public void add(int data) {
        //1. 检查顺序表是否已经填满了数据
        checkCapacity();

        //2. 把数据加到该顺序表的末尾
        elements[usedSize] = data;

        //3. usedSize++
        usedSize++;
    }

    @Override
    public void add(int pos, int data) throws PosIllegalException {
        //1.检查 pos 的合法性
        try {
            checkPosLegalityOnAdd(pos);
        } catch (PosIllegalException e) {
            e.printStackTrace();
            return;
        }
        //2. 检查顺序表是否已经填满了数据
        checkCapacity();

        //3. 把要插入的位置腾出来
        for(int i = usedSize-1; i >= pos; i--) {
            this.elements[i+1] = this.elements[i];
        }

        //4.插入数据
        this.elements[pos] = data;

        //5. usedSize++
        usedSize++;


    }
    /**
     * checkCapacity方法: 检查该顺序表中的位置是否够放数据
     * checkPosLegality方法: 检查用该位置访问顺序表是否合法
     */
    private void checkCapacity() {
        if(this.usedSize == this.elements.length) {
            this.elements = Arrays.copyOf(this.elements, this.elements.length * 2);
        }
    }
    private void checkPosLegalityOnAdd(int pos){
        if(pos < 0 || pos > this.usedSize) {
            throw new PosIllegalException("插入元素的位置不合法: " + pos);
        }
    }



    @Override
    public boolean contains(int toFind) {
        //如果顺序表什么都没有直接退出
        if(isEmpty()) {
            return false;
        }
        for(int i = 0; i < usedSize; i++)  {
            //如果是比较引用数据类型得用自己重写的 equals方法
            if(this.elements[i] == toFind) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int indexOf(int toFind) {
        //如果顺序表什么都没有返回 -1
        if(isEmpty()) {
            return -1;
        }
        for(int i = 0; i < usedSize; i++)  {
            //如果是比较引用数据类型得用自己重写的 equals方法
            if(this.elements[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public int get(int pos) throws PosIllegalException {
        //1. 检查 pos 的合法性
        try {
            posLegalityOnGetAndSet(pos);
        } catch (PosIllegalException e) {
            e.printStackTrace();
        }
        // 要考虑该顺序表是空空的情况
        if(isEmpty()) {
            throw new MyArrayListEmptyException("顺序表是空的,无法得到任何数据");
        }
        return this.elements[pos];
    }

    @Override
    public void set(int pos, int value) {
        //1. 检查 pos 的合法性
        try {
            posLegalityOnGetAndSet(pos);
        } catch (PosIllegalException e) {
            e.printStackTrace();
        }

        //2. 在该位置设置
        this.elements[pos] = value;
    }

    /**
     * posLegalityOnGetAndSet方法: 检查用该位置访问顺序表是否合法
     * @param pos
     */
    private void posLegalityOnGetAndSet(int pos) {
        if(pos < 0 || pos >= this.usedSize) {
            throw new PosIllegalException("查找或设置元素的下标异常: " + pos);
        }
    }

    @Override
    public void remove(int toRemove) {
        //1. 查找在顺序表中是否有这个数据
        if(contains(toRemove)) {
            //2. 删除数据(被覆盖)
            for(int i = indexOf(toRemove); i < this.usedSize - 1; i++) {
                this.elements[i] = this.elements[i+1];
            }
            //3. usedSize--
            usedSize--;
        }

    }

    @Override
    public int size() {
        return this.usedSize;
    }

    @Override
    public void clear() {
        this.usedSize = 0;
    }

    @Override
    public void display() {
        for(int i = 0; i < usedSize; i++) {
            System.out.print(this.elements[i] + " ");
        }
    }

    @Override
    public boolean isEmpty() {
        return this.usedSize == 0;
    }
}
